package cn.edu.lsu.integratedsurvey.service.impl;

import cn.edu.lsu.integratedsurvey.bean.History;
import cn.edu.lsu.integratedsurvey.bean.Student;
import cn.edu.lsu.integratedsurvey.bean.User;
import cn.edu.lsu.integratedsurvey.bean.dto.DataEntryDto;
import cn.edu.lsu.integratedsurvey.bean.dto.GetHistoryDto;
import cn.edu.lsu.integratedsurvey.bean.vo.HistoryInfoVo;
import cn.edu.lsu.integratedsurvey.exception.SystemException;
import cn.edu.lsu.integratedsurvey.mapper.HistoryMapper;
import cn.edu.lsu.integratedsurvey.mapper.StudentMapper;
import cn.edu.lsu.integratedsurvey.mapper.UserMapper;
import cn.edu.lsu.integratedsurvey.service.HistoryService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author Jasmine-drs
 * @description 针对表【history(综测历史记录表)】的数据库操作Service实现
 * @Date 2024-05-01 19:41:28
 */
@Service
public class HistoryServiceImpl extends ServiceImpl<HistoryMapper, History> implements HistoryService {

    private final HistoryMapper historyMapper;
    private final UserMapper userMapper;
    private final StudentMapper studentMapper;

    public HistoryServiceImpl(HistoryMapper historyMapper, UserMapper userMapper, StudentMapper studentMapper) {
        this.historyMapper = historyMapper;
        this.userMapper = userMapper;
        this.studentMapper = studentMapper;
    }

    @Override
    public Page<HistoryInfoVo> getHistories(GetHistoryDto getHistoryDto) {
//		构建分页对象
        Page<History> page = new Page<>(getHistoryDto.getPageNumber(), getHistoryDto.getPageSize());
        Page<History> historyPage;
//		构建条件查询
        LambdaQueryWrapper<History> wrapper = new LambdaQueryWrapper<>();
        if (getHistoryDto.getStudentNumber() != null && getHistoryDto.getType() != null) {
//			都不为null
            wrapper.eq(History::getStudentNumber, getHistoryDto.getStudentNumber())
                    .eq(History::getType, getHistoryDto.getType())
                    .between(History::getCreateTime, getHistoryDto.getStartDate(), getHistoryDto.getEndDate())
                    .orderBy(true, false, History::getCreateTime);
            historyPage = historyMapper.selectPage(page, wrapper);
        } else if (getHistoryDto.getStudentNumber() != null) {
//			学号不null
            wrapper.eq(History::getStudentNumber, getHistoryDto.getStudentNumber())
                    .between(History::getCreateTime, getHistoryDto.getStartDate(), getHistoryDto.getEndDate())
                    .orderBy(true, false, History::getCreateTime);
            historyPage = historyMapper.selectPage(page, wrapper);
        } else {
//			学号不能为null
            throw new SystemException("学号参数错误", 400);
        }
        System.out.println("historyPage = " + historyPage.getRecords());
//        转换成vo
        List<HistoryInfoVo> voList = historyPage.getRecords().stream()
                .map(HistoryInfoVo::convertToVo)
                .collect(Collectors.toList());
//      构造vo分页对象
        Page<HistoryInfoVo> voPage = new Page<>(historyPage.getCurrent(), historyPage.getSize(), historyPage.getTotal());
        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    public void updateStudent(DataEntryDto dataEntryDto) {
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getId, dataEntryDto.getOperatorId()));
        if (user == null) {
            throw new SystemException("当前账户异常，操作员不存在", 400);
        }
//		检查学生是否存在
        Student student = studentMapper.selectOne(new LambdaQueryWrapper<Student>().eq(Student::getStudentNumber, dataEntryDto.getStudentNumber()));
        if (student == null) {
            throw new SystemException("学生不存在", 400);
        }
        historyMapper.insert(dataEntryDto.convertToHistory(user));
    }

    @Override
    public void deleteHistory(String studentNumber) {
//		逻辑删除，具体数据清除由定时任务完成
        historyMapper.delete(new LambdaQueryWrapper<History>()
                .eq(History::getStudentNumber, studentNumber));
    }

    @Override
    @Transactional
    public void batchUpdateStudent(List<DataEntryDto> dataEntryDtoList) {
        // 收集所有操作员ID
        Set<String> operatorIds = dataEntryDtoList.stream()
                .map(DataEntryDto::getOperatorId)
                .collect(Collectors.toSet());

        // 一次性查询所有操作员信息
        Map<Integer, User> usersMap = userMapper.selectList(new LambdaQueryWrapper<User>()
                        .in(User::getId, operatorIds))
                .stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));

        // 验证操作员是否存在
        for (DataEntryDto dataEntryDto : dataEntryDtoList) {
            if (!usersMap.containsKey(Integer.valueOf(dataEntryDto.getOperatorId()))) {
                throw new SystemException("当前账户异常，操作员不存在", 400);
            }
        }
//		验证学生是否存在
//		收集所有学号
        Set<String> studentNumbers = dataEntryDtoList.stream()
                .map(DataEntryDto::getStudentNumber)
                .collect(Collectors.toSet());
//		一次性查询所有学生信息
        Map<String, Student> studentsMap = studentMapper.selectList(new LambdaQueryWrapper<Student>()
                        .in(Student::getStudentNumber, studentNumbers))
                .stream()
                .collect(Collectors.toMap(Student::getStudentNumber, Function.identity()));
//		判断学生是否存在，抛出具体学生不存在的异常
        List<String> list = new ArrayList<>();
        for (DataEntryDto dataEntryDto : dataEntryDtoList) {
            if (!studentsMap.containsKey(dataEntryDto.getStudentNumber())) {
                list.add(dataEntryDto.getStudentNumber());
            }
        }
        if (!list.isEmpty()) {
            throw new SystemException("以下学生不存在：" + String.join(", ", list), 400);
        }
        // 转换为历史记录并收集
        List<History> historyList = dataEntryDtoList.stream()
                .map(dataEntryDto -> dataEntryDto.convertToHistory(usersMap.get(Integer.valueOf(dataEntryDto.getOperatorId()))))
                .collect(Collectors.toList());

        // 批量插入历史记录
        if (!historyList.isEmpty()) {
            this.saveBatch(historyList);
        }
    }
}